#ifndef OPTIMIZER_H
#define OPTIMIZER_H

#include <map>
#include <utility>
#include <vector>
#include <string>
#include <iostream>
#include "ParseTree.h"
#include "Statistics.h"
#include "QueryPlanner.h"
#include "Record.h"
#include "Schema.h"

using namespace std;

struct s{
	string tableName;
	struct AndList* sel;
};
typedef struct s SelectData;

struct j{
	string joinName;
	struct AndList* sel;
	double numberOfTuples;
};
typedef struct j JoinData;


class JoinCmp{
public:
	bool operator()(const JoinData &a,const JoinData &b) const{
		return a.numberOfTuples < b.numberOfTuples;
	}
};

class Optimizer
{
	private:
		struct FuncOperator * FuncOp;
		struct TableList *  tList;
		struct AndList * andList;
		struct NameList *  groupingAtts; 
		struct NameList * attsToSelect; 
		int distinctAtts;  
		int distinctFunc; 
		int print; 
		string printPlanFile; 
		char ** tableNames;
		Statistics Stats;
		int tables,pipeID;
		OperatorNode *root;

		//vector for storing-> alias,andlist for iteration
		vector <SelectData> aliasSorted;
		vector <JoinData> joins;

		vector <string> andListVect;

		struct JoinEst{
			Statistics *stats;
			OperatorNode *opNode;
			string Order;
		};

		//map for storing interim status

		map <string, JoinEst> JoinEstimate;
		map <string, string> tablesMap; // alias to original table name
		map <int, string> OutPipeToCombo; // map of outpipe to combo name
		map <string, AndList*> aliasToAndList; // map of alias and their corresponding AndList
		map <AndList*, bool> andListFlag;

		// -------------- Member functions
		Optimizer();
		int GetAllAlias(); //storta alias name and puts in aliasToTable
		AndList* AndListSelection(string alias);  //matches Andlist and alias name for select
		AndList* AndListJoin( vector <string> &);  //matches Andlist and alias name for join
		void makeAndListVect(AndList*  inpParseTree);			//break andlist and put in vect
		void BaseCase(); // combo of 2 tables called during recursion
		int NextCombo(vector<string> &, string);  //searches for all combinations after finding first table
		vector<string> GetComboRelations(int length);	//recursive method for finding all combinations
		void TrimColumn(AndList*);                     //removes the prefix alias name
		void TrimColumn(FuncOperator&);                     //removes the prefix alias name
		void GetBestPair(vector<string>& ,  AndList* parseTree, pair<string, string> &); //find the best combination of tables
		OperatorNode * CreateSelectNode(string alias, int *num);
		Schema* MakeTree(OperatorNode*, OperatorNode*, string, int, int, int, int,Schema*,Schema*);
		void FinalizeTree(Schema*);

	public:
		Optimizer(Statistics &stat,             
				struct FuncOperator *functionStruct,
				struct TableList *tables,
				struct AndList * andL,
				struct NameList * grpAtts,
				struct NameList *  inpAttsToSelect,
				int inpDistinctAtts, int inpDistinctFunc, 
				int printScreenFlag, string planFile);                //intialized from main file
		void MakeQueryPlan();
		void ExecuteQuery();
		~Optimizer();
};

#endif
